package com.zzb.projectfactory.framework.common;

import com.zzb.projectfactory.framework.query.PageSearchForm;
import com.zzb.projectfactory.framework.query.QueryException;
import com.zzb.projectfactory.framework.role.entity.User;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 基本操作的service
 * Created by zhangzhenbin on 17-2-21.
 */
@Component
public abstract class BaseService<DAO extends BaseDAO<T, REPOSITORY>, T extends BaseEntity, REPOSITORY extends BaseRepository<T>> {
    @Autowired
    private GenericQueryDAO genericQueryDAO;

    /**
     * 获取实体dao对象
     */
    abstract public DAO getDAO();

    /**通过用户id获取实体*/
    public T get(String id){
        return getDAO().selectById(id);
    }

    /**
     * 回收
     */
    public BaseResponse<T> trash(String id, User operator) throws ServiceException {
        T t = get(id);
        return trash(t, operator);
    }
    /**
     * 回收
     */
    public BaseResponse<T> trash(T t, User operator) throws ServiceException {
        if(t == null) throw  new ServiceException("屏蔽失败，记录不存在");
        if(operator == null) throw  new ServiceException("屏蔽失败，请重新登录");
        if(!t.getActivate()) throw  new ServiceException("屏蔽失败，当前记录已被屏蔽");
        T trash = getDAO().trash(t, operator.getId());
        return new BaseResponse<T>(BaseResponse.SUCCESS,"屏蔽成功");
    }
    /**
     * 批量回收
     */
    public BaseResponse<List<T>> trashBatch(List<String> ids, User operator) throws ServiceException {
        List<T> ts = selectByIds(ids);
        return trash(ts, operator);
    }

    /**
     * 回收列表
     */
    public BaseResponse<List<T>> trash(List<T> ts, User operator) throws ServiceException {
        if(CollectionUtils.isEmpty(ts) ) throw  new ServiceException("屏蔽失败，请选择记录");
        if(operator == null) throw  new ServiceException("屏蔽失败，请重新登录");
        List<T> trash = getDAO().trash(ts, operator.getId());
        return new BaseResponse<>(BaseResponse.SUCCESS,"屏蔽成功",trash);
    }

    /**
     * 恢复
     */
    public BaseResponse<T>  recovery(String id, User operator) throws ServiceException {
        T t = get(id);
        return recovery(t,operator);
    }
    /**
     * 恢复
     */
    public BaseResponse<T>  recovery(T t, User operator) throws ServiceException {
        if(t == null) throw  new ServiceException("开启失败，记录不存在");
        if(operator == null) throw  new ServiceException("开启失败，请重新登录");
        if(t.getActivate()) throw  new ServiceException("开启失败，当前记录已开启");
        T recovery = getDAO().recovery(t, operator.getId());
        return new BaseResponse<T>(BaseResponse.SUCCESS,"开启成功",recovery);
    }
    /**
     * 恢复列表
     */
    public BaseResponse<List<T>> recoveryBatch(List<String> ids ,User operator) throws ServiceException{
        List<T> ts = selectByIds(ids);
        return recovery(ts,operator);
    }
    /**
     * 恢复列表
     */
    public BaseResponse<List<T>> recovery(List<T> ts, User operator) throws ServiceException {
        if(CollectionUtils.isEmpty(ts) ) throw  new DaoException("开启失败，请选择记录");
        if(operator == null) throw  new DaoException("开启失败，请重新登录");
        List<T> recovery = getDAO().recovery(ts, operator.getId());
        return new BaseResponse<>(BaseResponse.SUCCESS,"开启成功",recovery);
    }

    /**
     * 物理删除
     */
    public BaseResponse delete(String id) throws ServiceException {
        if(!exists(id))throw new ServiceException("删除失败，记录不存在");
        getDAO().delete(id);
        return new BaseResponse<>(BaseResponse.SUCCESS,"删除成功");
    }

    public BaseResponse delete(T t)  throws ServiceException {
        if(t==null)throw new ServiceException("删除失败，记录不存在");
        getDAO().delete(t);
        return new BaseResponse<>(BaseResponse.SUCCESS,"删除成功");
    }

    public BaseResponse delete(List<String> ids) throws ServiceException  {
        if(CollectionUtils.isEmpty(ids))throw new ServiceException("删除失败，记录不存在");
        getDAO().delete(ids);
        return new BaseResponse<>(BaseResponse.SUCCESS,"删除成功");
    }

    public BaseResponse deleteRecords(List<T> list) throws ServiceException  {
        if(CollectionUtils.isEmpty(list))throw new ServiceException("删除失败，记录不存在");
        getDAO().deleteRecords(list);
        return new BaseResponse<>(BaseResponse.SUCCESS,"删除成功");
    }


    /**
     * 保存或更新
     */
    public BaseResponse<T> createOrUpdate(T record, User operator) throws ServiceException {
        if(record == null) throw new ServiceException("保存失败，记录不能为空");
        if(operator == null) throw new ServiceException("保存失败，操作人不能为空");
        getDAO().createOrUpdate(record, operator.getId());
        return new BaseResponse<>(BaseResponse.SUCCESS,"保存成功",record);
    }

    public BaseResponse<List<T>> createOrUpdate(List<T> records, String operator)throws ServiceException {
        if(CollectionUtils.isEmpty(records)) throw new ServiceException("保存失败，记录不能为空");
        if(operator == null) throw new ServiceException("保存失败，操作人不能为空");
        getDAO().createOrUpdate(records,operator);
        return new BaseResponse<>(BaseResponse.SUCCESS,"保存成功",records);
    }


    /**
     * 插入，如果存在相同id抛异常
     */
    public BaseResponse<T> create(T record, User operator) throws ServiceException {
        if(record == null) throw new ServiceException("保存失败，记录不能为空");
        if(operator == null) throw new ServiceException("保存失败，操作人不能为空");
        getDAO().create(record,operator.getId());
        return new BaseResponse<>(BaseResponse.SUCCESS,"保存成功",record);
    }

    public BaseResponse<List<T>> create(List<T> records, User operator) throws ServiceException {
        if(CollectionUtils.isEmpty(records)) throw new ServiceException("保存失败，记录不能为空");
        if(operator == null) throw new ServiceException("保存失败，操作人不能为空");
        getDAO().create(records,operator.getId());
        return new BaseResponse<>(BaseResponse.SUCCESS,"保存成功",records);
    }

    /**
     * 更新，如果数据库中没有记录，则抛异常
     */
    public BaseResponse<T> update(T record, User operator) throws ServiceException {
        if(record == null) throw new ServiceException("保存失败，记录不能为空");
        if(operator == null) throw new ServiceException("保存失败，操作人不能为空");
        getDAO().update(record,operator.getId());
        return new BaseResponse<>(BaseResponse.SUCCESS,"保存成功",record);
    }

    public BaseResponse<List<T>> update(List<T> records, User operator) throws ServiceException {
        if(CollectionUtils.isEmpty(records)) throw new ServiceException("保存失败，记录不能为空");
        if(operator == null) throw new ServiceException("保存失败，操作人不能为空");
        getDAO().update(records,operator.getId());
        return new BaseResponse<>(BaseResponse.SUCCESS,"保存成功",records);
    }

    /**
     * 查找所有实体列表
     *
     * @return 返回实体列表
     */
    public List<T> selectAll() {
        return getDAO().selectAll();
    }

    public List<T> selectByIds(List<String> ids) {
        return getDAO().selectByIds(ids);
    }

    /**
     * 查找所有记录数
     *
     * @return 返回实体记录数
     */
    public long countAll() {
        return getDAO().countAll();
    }

    /**
     * 查询是否存在记录
     */
    public boolean exists(String id) {
        return getDAO().exists(id);
    }

    /**
     * 搜索分页
     * StringMatcher 选项如下
     * CONTAINING ->   LOWER(column) like '%' + LOWER(?) + '%'
     * DEFAULT -> column = ?
     * INSENSITIVE -> LOWER(column) = LOWER(?)
     * 可自定义StringMatcher
     */
    public BasePage<T> selectStringContainingPageByExample(T t, Pageable pageable) {
        return getDAO().selectStringContainingPageByExample(t,pageable);
    }
    public List<T> selectStringContainingListByExample(T t) {
        return getDAO().selectStringContainingListByExample(t);
    }

    public long countStringContainingListByExample(T t){
        return getDAO().countStringContainingListByExample(t);
    }


    public BasePage<T> selectStringDefaultPageByExample(T t, Pageable pageable){
        return getDAO().selectStringDefaultPageByExample(t, pageable);
    }
    public List<T> selectStringDefaultListByExample(T t){
        return getDAO().selectStringDefaultListByExample(t);
    }

    public long countStringDefaultListByExample(T t){
        return getDAO().countStringDefaultListByExample(t);
    }


    public BasePage<T> selectPageByExampleAndExampleMatcher(T t, Pageable pageable, ExampleMatcher exampleMatcher) {
        return getDAO().selectPageByExampleAndExampleMatcher(t,pageable,exampleMatcher);
    }
    public List<T> selectListByExampleAndExampleMatcher(T t, ExampleMatcher exampleMatcher) {
        return getDAO().selectListByExampleAndExampleMatcher(t,exampleMatcher);
    }

    public long countByExampleAndExampleMatcher(T t,ExampleMatcher exampleMatcher) {
        return getDAO().countByExampleAndExampleMatcher(t,exampleMatcher);
    }

    public BasePage<T> selectPageBySpecification(Specification<T> specification, Pageable pageable){
        return getDAO().selectPageBySpecification(specification,pageable);
    }
    public List<T> selectListBySpecification(Specification<T> specification){
        return getDAO().selectListBySpecification(specification);
    }
    public long countBySpecification(Specification<T> specification){
        return getDAO().countBySpecification(specification);
    }

    public BasePage<T> queryPage(String querySql, Class<T> clazz, int page ,int pageSize, Object... params) throws QueryException {
        return genericQueryDAO.queryPage(querySql, clazz, page, pageSize, params);
    }

    public <S extends PageSearchForm> BasePage<T> queryPage(S searchForm, Class<T> clazz) {
        return genericQueryDAO.queryPage(searchForm, clazz);
    }


}
